import java.awt.List;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

import camel.client.CamelRemote;
import camel.client.ClientEventChat;
import camel.client.ClientEvent;
import camel.client.CommandPack;
import camel.client.ParticipantLoginInfo;
import camel.client.SessionTicket;
import camel.client.ClientEvent;

public class UserThread extends Thread {
	private long start, end;
	private int id;
	
	CamelRemote camel;
	ParticipantLoginInfo info = new ParticipantLoginInfo();
	SessionTicket ticket;
	int internalCount = 0;
	
	public UserThread (CamelRemote camel, int id) {
		this.camel = camel;
		this.id = id;
	}
	
	public void addUser () {
		boolean isOK;
		info.setUsername("user_" + id);
		info.setPassword("1234");
		
		System.out.println ( "addUser");
		start = System.nanoTime();
		isOK = camel.addUserAdHoc(info);
		end = System.nanoTime();
		System.out.println ( "Last step : " + (double)(end-start)/1000000 + "msec");
		System.out.println("adduser " + isOK );
		
		//if (!isOK) {
		//	throw new RuntimeException("addUser failed for " + info.getUsername());
		//}
	}
	
	public void login () {
		System.out.println ( "login");
		start = System.nanoTime();
		ticket = camel.login(info);
		end = System.nanoTime();
		System.out.println ( "Last step : " + (double)(end-start)/1000000 + "msec");
		System.out.println("login " + ticket.isLogInSuccessful() );
		
		if (!ticket.isLogInSuccessful()) {
			throw new RuntimeException("login failed for " + info.getUsername());
		}
	}
	
	public void joinSession (Long sessionId) {
		System.out.println ( "join session");
		start = System.nanoTime();
		ticket = camel.joinSession(ticket, sessionId);
		end = System.nanoTime();
		System.out.println ( "Last step : " + (double)(end-start)/1000000 + "msec");
		System.out.println("join session " + ticket.isLogInSuccessful() );
		
		if (!ticket.isLogInSuccessful()) {
			throw new RuntimeException("login failed for " + info.getUsername());
		}
	}
	
	private CommandPack prepareCmdPack (int num) {
		CommandPack pack = new CommandPack(ticket);
		for(int i = 0; i < num; ++i, ++internalCount) {
			ClientEventChat cmd = new  ClientEventChat();
			cmd.setChatMsg("from " + ticket.getUsername() + " : msg " + internalCount);
			
			// used for testing purpose only
			cmd.setGeneralInfo(internalCount);
			
			DummyEvent event = new DummyEvent();
			event.setLine("Hello, this is mac " + internalCount);
			
			try {
				ByteArrayOutputStream b = new ByteArrayOutputStream();
				ObjectOutputStream out;
				out = new ObjectOutputStream(b);
				out.writeObject(event);
				//cmd.setFreeType(b.toByteArray());
				//cmd.setDataType(DummyEvent.class);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			
			pack.addCommand(cmd);
		}
		return pack;
	}
	
	public void run () {
		/*
		CommandPack postPack = prepareCmdPack(30);
		System.out.println ( "post");
		start = System.nanoTime();
		CommandPack replyPack = camel.postCommandPack(postPack);
		end = System.nanoTime();
		System.out.println ( "Last step : " + (double)(end-start)/1000000 + "msec");
		System.out.println("post " + ticket.isLastOpSuccessful() );
		
		postPack = prepareCmdPack(0);
		for(int i = 1; i < 10; ++i) {
						System.out.println ( "-----------------------------" );
			for(ClientCmdBase cmd : replyPack.getCmdList()) {
				if ( cmd instanceof ClientCmdChat) {
					ClientCmdChat chat = (ClientCmdChat)cmd;
					System.out.println ( ticket.getUsername() + " receives " + chat.getChatMsg());
				}
				else {
					throw new RuntimeException("Cannot recognize the event type");
				}
			}
			replyPack = camel.postCommandPack(postPack);
			
		}
		*/
		
		int sum = 0;
		int count = 0;
		System.out.println ( "post");
		start = System.nanoTime();
		for(int i = 0; i < 50; ++i) {
			CommandPack postPack = prepareCmdPack(5);
			camel.postCommandPack(postPack);
			CommandPack replyPack = camel.queryCommandPack(ticket, true);
			for(ClientEvent cmd : replyPack.getCmdList()) {
				if ( cmd instanceof ClientEventChat) {
					ClientEventChat chat = (ClientEventChat)cmd;
					sum += chat.getGeneralInfo();
					System.out.println(ticket.getUsername() + " receives " + chat.getChatMsg());
					/*
					try {
						ByteArrayInputStream b = new ByteArrayInputStream(chat.getFreeType());
						ObjectInputStream in = new ObjectInputStream(b);
						Class<?> x = DummyEvent.class;
						Object obj1 = in.readObject();
						if ( obj1 instanceof DummyEvent) {
							DummyEvent event = (DummyEvent)obj1;
							System.out.println("receives freetype event " + event.getLine());
						}
					} catch (ClassNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					*/
					
					++count;
				}
				else {
					//throw new RuntimeException("Cannot recognize the event type");
					System.out.println("Cannot recognize the event type");
				}
			}
			
			if ( i > 0 && (i%10 == 0)) {
				System.out.println ( ticket.getUsername() + " received " + count + " events" );
			}
		}
		end = System.nanoTime();
		System.out.println ( "Last step : " + (double)(end-start)/1000000 + "msec");
		System.out.println ( ticket.getUsername() + " received " + count + " events" );
		System.out.println ( ticket.getUsername() + " received sum from all users : " + sum );
		
		camel.logout(ticket);
	}
}
